/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package aso.upna.threads;

import aso.upna.controllers.SendInfo;
import aso.upna.filesystem.SharedFolder;
import aso.upna.p2pmessages.FailMessage;
import aso.upna.p2pmessages.OkMessage;
import aso.upna.p2pmessages.PlayMessage;
import aso.upna.p2pmessages.StopMessage;
import aso.upna.playlist.GenericIterator;
import aso.upna.playlist.GenericList;
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;

/**
 *
 * @author triki
 */
public class ClientAcceptedThread implements Runnable {

    private Socket sock;
    private SharedFolder shared;
    private GenericList ref_clients;

    public ClientAcceptedThread(Socket s,String path)
    {
        sock = s;
        shared = new SharedFolder(path,".mp3");
        ref_clients = null;
    }

    public void registerList(GenericList v)
    {
        ref_clients = v;
    }

    /*
     Nos mantendremos a la espera de recibir la peticion de cancion.
     Cuando recibamos el nombre de la cancion, le enviaremos un OK si
     la cancion se encuentra disponible. Acto seguido abriremos el
     fichero y le enviaremos la cancion. Si la cancion no se encuentra
     disponible, le mandaremos un FAIL.

     * Descripcion de los mensajes:
     * Reproducir una cancion.
        -Cliente remoto: "PLAY filexxx.mp3"
        -Cliente local: "OK :: [filesize en bytes]"
        -Cliente local: "FAIL"
    
     La conexion se cierra cuando se termina de enviar la cancion.
     */

    public void run()
    {   
        ObjectInputStream oisd = null;
        ObjectOutputStream oosd = null;
        SendInfo info = null;

        boolean end = false;
        byte[] message = new byte[1024];
        String sMessage = null;
        String[] parts;
        String filename = null;
        int remotePort = 0;
        DatagramSocket dgram;
        DatagramPacket dPack;
        byte[] aux = new byte[2048];
        InetAddress inaddr;
        UdpSenderThread send = null;
        Thread hiloSender = null;

        try
        {
            oosd = new ObjectOutputStream(sock.getOutputStream());
            oisd = new ObjectInputStream(sock.getInputStream());

            inaddr = sock.getInetAddress();

            info = new SendInfo(inaddr.getHostAddress());
            
            if(ref_clients != null)
            {
                synchronized(this)
                {
                    ref_clients.addElement(info);
                }
            }
            
            int j = 0;
            int read;
            Object obaux = null;

            while(true)
            {
                System.out.println("esperando a leer objeto");
                obaux = oisd.readObject();

                if(obaux instanceof PlayMessage)
                {
                    PlayMessage play = (PlayMessage)obaux;

                    info.setUserId(play.getUser());
                    info.setCancion(play.getCancion());
                    remotePort = play.getPort();

                    filename = new String(play.getCancion());

                     //buscamos la cancion
                     //Si la cancion existe, en enviamos un OK y el
                     //tamaño en bytes del fichero
                     String file_no = new String();
                    if(shared.searchFile(filename)) //&& new File(shared.getPath()+filename).exists())
                    {
                        file_no = shared.getRealPathTo(filename);
                        long aux2 = new File(file_no).length();
                        oosd.writeObject(new OkMessage(aux2));
                        System.out.println("size: "+aux2);
                        send = new UdpSenderThread(file_no,info,inaddr,remotePort,2048);
                        hiloSender = new Thread(send);
                        hiloSender.start();
                        continue;
                    }
                    else
                    {
                        String fail = "No existe el fichero pedido";
                        oosd.writeObject(new FailMessage(fail,1));
                        sock.close();
                        return;
                    }
                }

                if(obaux instanceof StopMessage)
                {
                    System.out.println(">>>>>>>>>>>>>>>>>>> end");
                    if(send != null)
                        hiloSender.interrupt();

                    oosd.writeObject(new FailMessage("end",0));
                    sock.close();
                    break;
                }    
                else
                {
                    String fail = "Funcion no reconocida";
                    oosd.writeObject(new FailMessage(fail,1));
                    sock.close();
                    return;
                }
            }
            
            //En este punto ya podemos cerrar:
            //  - socket TCP
            //  - ObjectInput
            //  - ObjectOutput
            
            oosd.close();
            oisd.close();
            sock.close();

            if(ref_clients != null)
            {
                synchronized(this)
                {
                    ref_clients.remove(info);
                }
            }

            //En este punto estamos seguros de podemos algo a un sitio seguro.
           
            /*System.out.println("Opening UDP socket..");
            //Abrimos un nuevo socket UDP.
            dgram = new DatagramSocket();

            File f = new File(shared.getPath()+filename);
            FileInputStream ifile = new FileInputStream(f);
            
            int size = 0;

            info.setTotal(f.length());
            info.setEnviado(size);

            while(ifile.read(aux) > -1)
            {
                try
                {
                    dPack = new DatagramPacket(aux,2048,inaddr,remotePort);
                    dgram.send(dPack);
                    size+=2048;
                    info.setEnviado(size);
                    
                    //Esperamos 50ms para no atragantar el socket de recepcion
                    Thread.sleep(50);
                }
                catch (InterruptedException ex)
                {
                        ex.printStackTrace();
                }

            }
            
            if(ref_clients != null)
            {
                synchronized(this)
                {
                    ref_clients.remove(info);
                    GenericIterator iter = ref_clients.getIterator();
                }
            }
            
            dgram.close();*/
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
}
